/*
 * TextField.java  0.4.0 / Oct 27, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
package com.cute4j.swing;

import com.cute4j.swing.events.ActionEvent;
import com.cute4j.swing.events.ActionListener;
import com.cute4j.swing.events.SwingEvent;
import com.cute4j.swing.properties.TextFieldProperties;

/**
 * Text Field Component.
 *
 * @cute4j.native
 *    generate="header"
 *
 * @author Slobodan Vrkacevic
 * @version 0.4.0
 */
public class TextField extends Component
                       implements SwingConstants, TextFieldProperties {

  // TODO: Extend TextComponent class.

// Static Initialization. ------------------------------------------------------

  static {
    _initialize();
  }

// Package-Private Fields. -----------------------------------------------------

  String text; // TODO: temp - use text document
  String actionCommand;
  int horizontalAlignment;

// Public Constructors. --------------------------------------------------------

  /**
   * Constructs new TextField object.
   */
  public TextField() {
    // empty constructor body
  }

  /**
   * Constructs new TextField object.
   *
   * @param text the text
   */
  public TextField(String text) {
    if (text != null) {
      this.text = text;
      _setText(_delegate, text); // NOPMD
    }
  }

// Public Methods. -------------------------------------------------------------

  /**
   * Returns text.
   *
   * @return text
   */
  public String getText() {
    disposedCheck();
    return _getText(_delegate);
  }

  /**
   * Sets text.
   *
   * @param text the text
   */
  public void setText(String text) {
    disposedCheck();
    _setText(_delegate, text);
  }

  /**
   * Returns horizontal alignment.
   *
   * @return horizontal alignment
   */
  public int getHorizontalAlignment() {
    return horizontalAlignment;
  }

  /**
   * Sets horizontal alignment.
   * <p>Valid values are: <tt>LEFT</tt>, <tt>CENTER</tt>, <tt>RIGHT</tt>,
   *                      <tt>LEADING</tt> and <tt>TRAILING</tt>.
   * <br/>
   *   Default value is: <tt>LEADING</tt>.
   * </p>
   *
   * @param alignment the horizontal alignment
   */
  public void setHorizontalAlignment(int alignment) {
    int oldHorizontalAlignment = horizontalAlignment;
    if (oldHorizontalAlignment != alignment) {
      disposedCheck();
      horizontalAlignment = checkHorizontalKey(alignment,
                                               "Invlid horizontal alignment");
      _setHorizontalAlignment(_delegate, alignment);
      firePropertyChange(PROPERTY_HORIZONTAL_ALIGNMENT, oldHorizontalAlignment,
                         alignment);
    }
  }

  /**
   * Returns action command.
   *
   * @return action command
   */
  public String getActionCommand() {
    if (actionCommand == null) {
      return getText();
    }
    return actionCommand;
  }

  /**
   * Sets action command for this button.
   *
   * @param actionCommand the action command
   */
  public void setActionCommand(String actionCommand) {
    final String oldActionCommand = this.actionCommand;
    if (oldActionCommand == null) {
      if (actionCommand == null) {
        return;
      }
    } else {
      if (oldActionCommand.equals(actionCommand)) {
        return;
      }
    }
    this.actionCommand = actionCommand;
    firePropertyChange(PROPERTY_ACTION_COMMAND, oldActionCommand,
                       actionCommand);
  }

  /**
   * Adds action listener.
   *
   * @param listener the action listener
   */
  public void addActionListener(ActionListener listener) {
    if (listener != null) {
      enableEvents(SwingEvent.ACTION_EVENT_MASK);
      listenerList.add(ActionListener.class, listener);
    }
  }

  /**
   * Remove action listener.
   *
   * @param listener the action listener
   */
  public void removeActionListener(ActionListener listener) {
    if (listener != null) {
      listenerList.remove(ActionListener.class, listener);
      if (listenerList.getListenerCount(ActionListener.class) == 0) {
        disableEvents(SwingEvent.ACTION_EVENT_MASK);
      }
    }
  }

  /**
   * Returns all action listeners.
   *
   * @return the action listener array
   */
  public ActionListener[] getActionListeners() {
    int count = listenerList.getListenerCount(ActionListener.class);
    ActionListener[] listeners = new ActionListener[count];
    if (count > 0) {
      System.arraycopy(listenerList.getListenersArray(ActionListener.class), 0,
                       listeners,  0, count);
    }
    return listeners;
  }

// Protected Methods. ----------------------------------------------------------

  /**
   * Checks horizontal alignment key.
   *
   * @param key the key
   * @param message the error message
   *
   * @return alignment key
   *
   * @throws IllegalArgumentException if the key is invalid
   */
  protected final int checkHorizontalKey(int key, String message) {
    if ((key == LEFT) || (key == CENTER) || (key == RIGHT) ||
        (key == LEADING) || (key == TRAILING)) {
      return key;
    }
    throw new IllegalArgumentException(message);
  }

  /**
   * Fires action event.
   *
   * @param e the action event
   */
  protected void fireActionPerformed(ActionEvent e) {
    int count = listenerList.getListenerCount(ActionListener.class);
    if (count > 0) {
      ActionListener[] listeners = (ActionListener[])listenerList.
                                       getListenersArray(ActionListener.class);
      for (int i = count; --i >= 0;) {
        listeners[i].actionPerformed(e);
      }
    }
  }

// Native Callbacks. -----------------------------------------------------------

  void _returnPressed(int modifiers) {
    fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
                                        getActionCommand(),
                                        System.currentTimeMillis(), modifiers));
  }

// Package-Private Native Methods. ---------------------------------------------

  native long _create();

  native String _getText(long delegate);

  native void _setText(long delegate, String text);

  native void _setHorizontalAlignment(long delegate, int alignment);

// Private Static Native Methods. ----------------------------------------------

  private static native void _initialize();

}
